#include "stdafx.h"
#include "CppUnitTest.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace NMemoryManagerTest
{
	TEST_CLASS(NMemoryManagerStTest)
	{
	public:
		
		void CheckMem( void* pMem, int nSize )
		{
			Assert::IsNotNull( pMem );
			ZeroMemory( pMem, nSize );
			int* pMemInspector = (int*)pMem;
			Assert::AreEqual( *(pMemInspector - 1), nSize );

			int nAllocationSize = (nSize + 8);

			Assert::AreEqual( *(pMemInspector - 2),  
								static_cast<int>( ( nAllocationSize >= CNMemoryManagerST::cnMaxSizeWhichCanUseMemoryChunk ) ?
													-1 : (nAllocationSize / CNMemoryManagerST::cnMemoryChunkAlignBase) ) );
		}

		TEST_METHOD(NMemoryManagerST_Alloc_Free)
		{
			CNMemoryManagerST MemoryManagerST;

			const int cnTestAllocSize = 1024;

			std::vector<void*> vecMemory;
			vecMemory.reserve( cnTestAllocSize );

			for ( int nSize = 1; nSize < cnTestAllocSize; ++nSize )
			{
				void* pMem = MemoryManagerST.Alloc( nSize );
				CheckMem( pMem, nSize );

				vecMemory.push_back( pMem );
			}

			for ( void*& pMem : vecMemory )
			{
				MemoryManagerST.Free( pMem );
			}
		}


		TEST_METHOD(NMemoryManagerST_Faster_Than_New_Delete_Random_1_1024)
		{
			CNMemoryManagerST MemoryManagerST;

			const int cnMaxMemorySize	= 1024;
			const int cnLoopCount		= 100000;

			std::vector<void*> vecContainer;
			vecContainer.reserve( cnLoopCount );

			ULONGLONG ullLastTickForMemoryManagerST = GetTickCount64();

			for ( int nCur = 0; nCur < cnLoopCount; ++nCur )
			{
				int nSize = RangedRand(1, cnMaxMemorySize);

				vecContainer.push_back( MemoryManagerST.Alloc( nSize ) );
			}

			for ( void*& pMem : vecContainer )
			{
				MemoryManagerST.Free( pMem );
			}

			ULONGLONG ullElapseTickForMemoryManagerST = GetTickCount64() - ullLastTickForMemoryManagerST;

			vecContainer.clear();
			vecContainer.reserve( cnLoopCount );


			
			ULONGLONG ullLastTickForNewDelete = GetTickCount64();

			for ( int nCur = 0; nCur < cnLoopCount; ++nCur )
			{
				int nSize = RangedRand(1, cnMaxMemorySize);

				vecContainer.push_back( new char[nSize] );
			}

			for ( void*& pMem : vecContainer )
			{
				delete pMem;
			}

			ULONGLONG ullElapseTickForNewDelete = GetTickCount64() - ullLastTickForNewDelete;


			Assert::IsTrue( ullElapseTickForNewDelete > ullElapseTickForMemoryManagerST );
		}
	};
}